<?php

/*
# 最后一次索引位置 表结构
CREATE TABLE `t_signfield` (
`_id` int(11) unsigned PRIMARY KEY AUTO_INCREMENT COMMENT '主键',
`name` varchar(250) COMMENT '名称',
`value` int(11)  DEFAULT NULL COMMENT '最后一次索引',
UNIQUE KEY `name` (`name`)    -- 唯一键
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
*/

// $SignField = new SignField();
// $res = $SignField->record("lastIndex", 1);   //增
// $res = $SignField->update("lastIndex", 20);  //改
// $res = $SignField->getVal("lastIndex");      //查

class SignFieldDB
{
    /**
     * @var \PDO $pdo
     */
    protected $pdo = null;
    protected static $instance = null;
    protected $table_name = "t_signfield";

    protected $config = [
        "host" => "127.0.0.1",
        "db_name" => "fancyalarm",
        "user_name" => "root",
        "password" => "root",
    ];

    /**
     * 创建db连接
     *
     *
     * @return SignFieldDB|null
     */
    public static function connect()
    {
        if (self::$instance == null) {
            self::$instance = new self();
        }
        return self::$instance;
    }


    /**
     * 获取实例
     *
     * @return PDO
     * @throws SignFieldException
     */
    protected function db()
    {
        try {
            if (empty($this->pdo)) {
                $host = $this->config['host'];
                $db_name = $this->config['db_name'];
                $this->pdo = new PDO("mysql:host={$host};dbname={$db_name};charset=utf8", $this->config['user_name'], $this->config['password']);
            }
        } catch (\PDOException $e) {
            throw new SignFieldException("数据库连接失败:" . $e->getMessage(), $e->getCode());
        }
        return $this->pdo;
    }


    /**
     * 执行sql
     *
     *
     * @param string $sql
     * @return array|bool
     * @throws SignFieldException
     */
    public function query($sql)
    {
        $is_action = false;
        if (strpos($sql, "insert") !== false || strpos($sql, "update") !== false
            || strpos($sql, "create") !== false || strpos($sql, "drop") !== false || strpos($sql, "alter") !== false) {
            $is_action = true;
        }
        try {
            $db = $this->db();
            if ($is_action) {
                $result = $db->prepare($sql);
                return $result->execute();//返回受影响的记录条数,num为int类型;
            }
            $stmt = $db->query($sql);
            $rows = [];
            while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
                $rows[] = $row;
            }
            return $rows;
        } catch (\PDOException $e) {
            throw new SignFieldException($e->getMessage());
        }
    }

    /**
     * 查询集合
     *
     *
     * @param $sql
     * @return array|bool
     * @throws SignFieldException
     */
    public function select($sql)
    {
        return $this->query($sql);
    }
    
    /**
     * 查询一个
     *
     *
     * @param string $sql
     * @return array|mixed
     * @throws SignFieldException
     */
    public function first($sql)
    {
        $result = $this->select($sql);
        return empty($result) ? [] : array_shift($result);
    }

    /**
     * 添加操作
     *
     *
     * @param array $data
     * @return bool
     * @throws SignFieldException
     */
    public function add($data)
    {

        try {
            if (!is_array($data)) {
                return false;
            }
            $data = $this->filterData($data);
            if (empty($data)) {
                return false;
            }
            $field = $this->bindField($data);

            $value = $this->bindValue($data);
            $sql = "insert into {$this->table_name} set %s";


            $result = $this->db()->prepare(vsprintf($sql, implode(",", $field)));
            return $result->execute($value);//返回受影响的记录条数,num为int类型;
        } catch (\PDOException $e) {
            throw new SignFieldException($e->getMessage());
        }
    }


    /**
     * 更新操作
     *
     *
     * @param $data
     * @param $where
     * @return bool
     * @throws SignFieldException
     */
    public function update($data, $where)
    {
        try {
            if (empty($data)) {
                return false;
            }
            if (!is_array($data)) {
                return false;
            }
            $data = $this->filterData($data);

            $field = $this->bindField($data);

            $value = $this->bindValue($data);

            $sql = "update {$this->table_name} set %s where 1 = 1 and " . $where;

            $result = $this->db()->prepare(vsprintf($sql, implode(",", $field)));

            return $result->execute($value);//返回受影响的记录条数,num为int类型;
        } catch (\PDOException $e) {
            throw new SignFieldException($e->getMessage());
        }
    }

    /**
     * 过滤空值
     *
     *
     * @param $data
     * @return array
     */
    protected function filterData($data)
    {
        return array_filter($data, function ($v) {
            return !empty($v);
        });
    }


    /**
     * 绑定字段
     *
     *
     * @param $data
     * @return array
     */
    protected function bindField($data)
    {
        $field = array_map(function ($v) {
            return $v . "=:" . $v;
        }, array_keys($data));
        return $field;
    }

    /**
     * 绑定值
     *
     *
     * @param $data
     * @return array
     */
    protected function bindValue($data)
    {
        $value = [];
        array_walk($data, function ($v, $k) use (&$value) {
            $value[":" . $k] = $v;
        });
        return $value;
    }

    /**
     * 关闭连接
     *
     *
     */
    public function close()
    {
        $this->pdo = null;
    }
}

class SignField{
    /**
     * 名字
     * @var $name
     */
    protected $name = '';

    public function __construct()
    {
        $this->_init();
    }

    /**
     *
     *
     * @return void
     */
    protected function _init()
    {
    }

    /**
     * 异常记录
     *
     *
     * @param $exception
     */
    public function recordException($exception)
    {

    }

     /**
     * 存储
     * 
     * @param string $name 名字key
     * @param string $value 值
     * @return array|bool
     */
    public function record($name, $value)
    {

        $result = false;
        try {
            do {
                $this->name = $name;
                $this->value = $value;

                $this->db = SignFieldDB::connect();
                $result = $this->store($name, $value);
                break;
            } while (null);
        } catch (SignFieldException $exception) {
            $result = false;
        } catch (Exception $exception) {
            $result = false;
        }

        // 关闭数据库连接实例
        if ($this->db instanceof SignFieldDB) {
            $this->db->close();
        }

        return $result;
    }

    /**
     * 保存
     *
     * @param $name
     * @param $value
     * @return bool
     */
    protected function store($name, $value)
    {
        try {
            $res = $this->db->add([
                "name" => $name,
                "value" => $value,
            ]);
            if ($res === false) {
                return false;
            }
        } catch (SignFieldException $e) {
            return false;
        }
        return true;
    }

    /**
     * 更新
     *
     * @param $name
     * @param $value
     * @return bool
     */
    public function update($name, $value)
    {
        try {
            $this->db = SignFieldDB::connect();
            $res = $this->db->update(["value" => $value],"name='$name'");
            if ($res === false) {
                return false;
            }
        } catch (SignFieldException $e) {
            return false;
        }
        return true;
    }                                                                                                                     
  
    
    /**
     * 获得值
     *
     * @param $name
     * @return number
     */
    public function getVal($name)
    {
        try {
            $this->db = SignFieldDB::connect();
            $res = $this->db->first("select value as value from t_signfield where name = '$name'");
            return $res['value'];
        } catch (SignFieldException $e) {
            return "";
        }
        return "";
    }   
}

class SignFieldException extends Exception
{

}
